#pragma once
#include <memory>
#include <functional>
#include "field.hpp"

namespace RPC
{

    class BaseMessage
    {
    public:
        using Ptr = std::shared_ptr<BaseMessage>;
        virtual void setType(MType type)
        {
            _mtype = type;
        }

        virtual MType type()
        {
            return _mtype;
        }

        virtual void setId(std::string id)
        {
            _rid = id;
        }

        virtual std::string id()
        {
            return _rid;
        }

        virtual std::string serialize() = 0;
        virtual bool desrialize(const std::string &) = 0;
        virtual bool check() = 0;

    private:
        MType _mtype;
        std::string _rid;
    };

    class BaseBuffer
    {

    public:
        using Ptr = std::shared_ptr<BaseBuffer>;
        virtual size_t readAbleSize() = 0;
        virtual int32_t peekInt32_t() = 0;
        virtual void retrieveInt32_t() = 0;
        virtual int32_t readInt32_t() = 0;
        virtual std::string retrieveAsString(size_t len) = 0;

    private:
    };

    class BaseProtocol
    {
    public:
        using Ptr = std::shared_ptr<BaseProtocol>;
        virtual bool canProcessd(const BaseBuffer::Ptr &buffer) = 0;
        virtual bool onMessage(const BaseBuffer::Ptr &basebuffer, 
            BaseMessage::Ptr &message) = 0;
        virtual std::string serialize(const BaseMessage::Ptr &message) = 0;
    };

    class BaseConnection
    {
    public:
        using Ptr = std::shared_ptr<BaseConnection>;
        virtual void shutdown() = 0;
        virtual void send(const BaseMessage::Ptr &msg) = 0;
        virtual bool connected() = 0;
    };

    using ConnetctionCallback = std::function<void()>;
    using CloseCallback = std::function<void(const BaseConnection::Ptr &)>;
    using MessageCallback = std::function<void(const BaseConnection::Ptr &, BaseMessage::Ptr &)>;

    class BaseServer
    {
    public:
        using Ptr = std::shared_ptr<BaseServer>;

        virtual void setConnectionCallback(const ConnetctionCallback& cb)
        {
            _cb_connecton = cb;
        }
        virtual void setCloseCallback(CloseCallback cb)
        {
            _cb_close = cb;
        }
        virtual void setMessageCallback(MessageCallback cb)
        {
            _cb_message = cb;
        }

        virtual void start() = 0;

    protected:
        ConnetctionCallback _cb_connecton;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };

    class BaseClient
    {
    public:
        using Ptr = std::shared_ptr<BaseClient>;

        virtual void SetConnectionCallback(ConnetctionCallback cb)
        {
            _cb_connection = cb;
        }
        virtual void SetCloseCallback(CloseCallback cb)
        {
            _cb_close = cb;
        }
        virtual void SetMessageCallback(MessageCallback cb)
        {
            _cb_message = cb;
        }

        virtual bool connected() = 0;                    // 判断连接是否存在
        virtual void connect() = 0;                      // 连接服务器
        virtual void shutdown() = 0;                     // 关闭服务器
        virtual void send(const BaseMessage::Ptr &) = 0; // 发送消息
        virtual BaseConnection::Ptr conn() = 0;
    protected:
        ConnetctionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_message;
    };
}